/**
 * Date:2021年9月2日 下午9:00:59
 * Copyright (c) 2021, www.bwbroad.com All Rights Reserved
 */

package com.xue.config;

import java.util.ArrayList;
import java.util.List;
import java.util.Properties;

import javax.sql.DataSource;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.jdbc.DataSourceProperties;
import org.springframework.boot.autoconfigure.orm.jpa.HibernateProperties;
import org.springframework.boot.autoconfigure.orm.jpa.HibernateSettings;
import org.springframework.boot.autoconfigure.orm.jpa.JpaProperties;
import org.springframework.boot.autoconfigure.sql.init.SqlInitializationProperties;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.jdbc.DataSourceBuilder;
import org.springframework.boot.jdbc.init.DataSourceScriptDatabaseInitializer;
import org.springframework.boot.orm.jpa.EntityManagerFactoryBuilder;
import org.springframework.boot.sql.init.DatabaseInitializationSettings;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
import org.springframework.jdbc.datasource.SimpleDriverDataSource;
import org.springframework.orm.jpa.JpaVendorAdapter;
import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean;
import org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter;
import org.springframework.util.StringUtils;

import com.atomikos.jdbc.AtomikosDataSourceBean;

@Configuration
@EnableJpaRepositories(basePackages = { Ds1RepositoryConfig.PACKAGE }, // 设置dao（repo）所在位置
		entityManagerFactoryRef = "ds1EntityManagerFactory"/* , transactionManagerRef = "transactionManager" */)
public class Ds1RepositoryConfig {
	public static final String PACKAGE = "com.xue.dao.ds1";
	
	//等同于 @ConfigurationProperties(prefix = "spring.jpa")
	@Autowired
	private JpaProperties jpaProperties;//spring.jpa

	//等同于 @ConfigurationProperties(prefix = "spring.jpa.hibernate")
	@Autowired
	private HibernateProperties hibernateProperties;

	// 获取数据源配置
	@Bean(name = "ds1Properties")
	@ConfigurationProperties(prefix = "spring.datasource.ds1")
	public DataSourceProperties ds1Properties() {
		return new DataSourceProperties();// 注意是url 而不是jdbc-url
	}

//	@Bean(name = "ds1")
//	@ConfigurationProperties(prefix = "spring.datasource.ds1")
//	public DataSource ds1() {
//		return DataSourceBuilder.create().build();
//	}

// xml 配置如下
//	<bean id="userDataSource" class="com.atomikos.jdbc.AtomikosDataSourceBean"
//			init-method="init" destroy-method="close"  lazy-init="true">
//			<property name="uniqueResourceName" value="mysql_user" />
//			<property name="xaDataSourceClassName"
//				value="com.mysql.jdbc.jdbc2.optional.MysqlXADataSource" />
//			<property name="xaProperties">
//				<props>    
//	                <prop key="URL">${jdbc.user.url}</prop>    
//	               	<prop key="user">${jdbc.user.username}</prop>    
//	                <prop key="password">${jdbc.user.password}</prop>    
//	           </props>
//			</property>
//			<property name="poolSize"><value>1</value></property>      
//	        <property name="maxPoolSize"><value>30</value></property>
//		</bean

	// 配置数据源
	@Primary
	@Bean(name = "ds1")
	public DataSource ds1() {
		DataSourceProperties dsp = ds1Properties();
		AtomikosDataSourceBean atomikosDataSourceBean = new AtomikosDataSourceBean();
		atomikosDataSourceBean.setUniqueResourceName(dsp.getName());
		atomikosDataSourceBean.setXaDataSourceClassName(dsp.getXa().getDataSourceClassName());
		atomikosDataSourceBean.setPoolSize(5);
		Properties xaProperties = new Properties();
		xaProperties.setProperty("URL", dsp.getUrl());
		xaProperties.setProperty("user", dsp.getUsername());
		xaProperties.setProperty("password", dsp.getPassword());
		atomikosDataSourceBean.setXaProperties(xaProperties);
		return atomikosDataSourceBean;
	}

	private JpaVendorAdapter jpaVendorAdapter() {
		HibernateJpaVendorAdapter jpaVendorAdapter = new HibernateJpaVendorAdapter();
		// 设置数据库类型（可使用org.springframework.orm.jpa.vendor包下的Database枚举类）
		jpaVendorAdapter.setDatabase(jpaProperties.getDatabase());
		// 设置打印sql语句
		jpaVendorAdapter.setShowSql(jpaProperties.isShowSql());
		// 设置不生成ddl语句
		jpaVendorAdapter.setGenerateDdl(jpaProperties.isGenerateDdl());
		// 设置hibernate方言
		// jpaVendorAdapter.setDatabasePlatform("org.hibernate.dialect.MySQL5Dialect");
		// jpaVendorAdapter.setDatabasePlatform("org.hibernate.dialect.H2Dialect");
		return jpaVendorAdapter;
	}

//	@Bean
//	public JdbcTemplate ds1JdbcTemplate(@Qualifier("ds1") DataSource ds) {
//	        return new JdbcTemplate(ds);
//	}

	@Bean(name = "ds1EntityManagerFactory")
	@Primary
	public LocalContainerEntityManagerFactoryBean entityManagerFactory() {
		LocalContainerEntityManagerFactoryBean entityManager = new LocalContainerEntityManagerFactoryBean();
		entityManager.setJtaDataSource(ds1());
		entityManager.setJpaVendorAdapter(jpaVendorAdapter());
		entityManager.setPackagesToScan(PACKAGE);
		entityManager.setPersistenceUnitName("ds1PersistenceUnit");
		entityManager.setJpaPropertyMap(hibernateProperties.determineHibernateProperties(jpaProperties.getProperties(),
				new HibernateSettings()));
		return entityManager;

	}

//-----------------------------------------
	// 初始化ds1的脚本的配置信息
	@Bean(name = "init")
	@ConfigurationProperties(prefix = "spring.sql.init")
	public SqlInitializationProperties initConfig() {
		return new SqlInitializationProperties();
	}

	// 执行初始化脚本
	// org.springframework.boot.autoconfigure.sql.init.DataSourceInitializationConfiguration.class
	// DataSourceScriptDatabaseInitializer
	@Bean("ds1Inint")
	DataSourceScriptDatabaseInitializer dataSourceScriptDatabaseInitializer() {
		SqlInitializationProperties initializationProperties = initConfig();
		DatabaseInitializationSettings settings = createFrom(initializationProperties);
		return new DataSourceScriptDatabaseInitializer(determineDataSource(ds1(),
				initializationProperties.getUsername(), initializationProperties.getPassword()), settings);
	}

	static DatabaseInitializationSettings createFrom(SqlInitializationProperties properties) {
		DatabaseInitializationSettings settings = new DatabaseInitializationSettings();
		settings.setSchemaLocations(
				scriptLocations(properties.getSchemaLocations(), "schema", properties.getPlatform()));
		settings.setDataLocations(scriptLocations(properties.getDataLocations(), "data", properties.getPlatform()));
		settings.setContinueOnError(properties.isContinueOnError());
		settings.setSeparator(properties.getSeparator());
		settings.setEncoding(properties.getEncoding());
		settings.setMode(properties.getMode());
		return settings;
	}

	private static List<String> scriptLocations(List<String> locations, String fallback, String platform) {
		if (locations != null) {
			return locations;
		}
		List<String> fallbackLocations = new ArrayList<>();
		fallbackLocations.add("optional:classpath*:" + fallback + "-" + platform + ".sql");
		fallbackLocations.add("optional:classpath*:" + fallback + ".sql");
		return fallbackLocations;
	}

	private static DataSource determineDataSource(DataSource dataSource, String username, String password) {
		if (StringUtils.hasText(username) && StringUtils.hasText(password)) {
			return DataSourceBuilder.derivedFrom(dataSource).username(username).password(password)
					.type(SimpleDriverDataSource.class).build();
		}
		return dataSource;
	}

}
